#include "StdAfx.h"

BrowsingUI* Singleton<BrowsingUI>::m_instance = 0;

void ElementClicked(void* pAsync, TreeViewItem* pItem)
{
	std::string szFinal = pItem->GetText();
	while(pItem->GetParent())
	{
		pItem = pItem->GetParent();
		std::string szThis = pItem->GetText();
		szThis += '\\';
		szThis += szFinal;
		szFinal = szThis;
	}
	((BrowsingUI*)pAsync)->OnItemSelected(szFinal);
}

void Expanded(void* pAsync, ui32 index)
{
	((BrowsingUI*)pAsync)->Expanded(index);
}

BrowsingUI::BrowsingUI()
{
	m_pModel = 0;
	m_pPreview = 0;
	m_position.x = 144.0f;
	m_position.y = 100.0f;

	m_pTopLeft = sTexture.GetTexture("Interface\\Spellbook\\UI-SpellbookPanel-TopLeft.blp");
	m_pTopRight = sTexture.GetTexture("Interface\\Spellbook\\UI-SpellbookPanel-TopRight.blp");
	m_pBotRight = sTexture.GetTexture("Interface\\Spellbook\\UI-SpellbookPanel-BotRight.blp");
	m_pBotLeft = sTexture.GetTexture("Interface\\Spellbook\\UI-SpellbookPanel-BotLeft.blp");

	ReloadVertices();

	m_rotationY = 0.0f;

	m_titleClicked = false;
	m_pModelTree = new TreeView(m_position.x + 30, m_position.y + 80 + 160, 200, 180);
	m_pModelTree->SetCallback(ElementClicked, this);
	m_pModelTree->ScrollSetCallback(::Expanded, this);
	LoadModels();
	m_pTreeScroll = new VScrollbar<BrowsingUI>(m_position.x + 300, m_position.y + 80 + 160, 180, this);
	m_pTreeScroll->SetCallback(&BrowsingUI::ScrollBarProc);
	m_pTreeScroll->SetRange(0, m_pModelTree->GetNumItems() - 1);
	m_numLastItems = m_pModelTree->GetNumItems() - 1;
}

void BrowsingUI::OnItemSelected(std::string wmo)
{
	MODF mdf;
	mdf.uniqueId = 0xFFFFFFFF;
	WMOModel* mod = new WMOModel(wmo, mdf);
	if(mod->Init())
	{
		m_pModel = mod;
		return;
	}

	if(mod)
		delete mod;
	m_pModel = 0;
}

void BrowsingUI::Expanded(ui32 index)
{
	m_pTreeScroll->SetValue(index);
}

void BrowsingUI::ScrollBarProc(VScrollbar<BrowsingUI>* pBar, ui32 value)
{
	m_pModelTree->SetScroll(value);
}

void BrowsingUI::Render2D()
{
	return;
	sD3D->SetFVF(VERTEX3FRHWT);
	sD3D->SetTexture(0, *m_pTopRight);
	sD3D->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, m_topR, sizeof(Vertex3FRHWT));
	sD3D->SetTexture(0, *m_pTopLeft);
	sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, m_topL, sizeof(Vertex3FRHWT));
	sD3D->SetTexture(0, *m_pBotLeft);
	sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, m_botL, sizeof(Vertex3FRHWT));
	sD3D->SetTexture(0, *m_pBotRight);
	sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, m_botR, sizeof(Vertex3FRHWT));

	if(m_pModel && m_pPreview)
	{
		Vertex3FRHWT backg[4];
		backg[0].x = m_position.x + 40.0f;
		backg[0].y = m_position.y + 80.0f;
		backg[1].x = m_position.x + 190.0f;
		backg[1].y = m_position.y + 80.0f;
		backg[2].x = m_position.x + 190.0f;
		backg[2].y = m_position.y + 230.0f;
		backg[3].x = m_position.x + 40.0f;
		backg[3].y = m_position.y + 230.0f;
		backg[0].u = backg[3].u = backg[0].v = backg[1].v = 0.0f;
		backg[1].u = backg[2].u = backg[3].v = backg[2].v = 1.0f;
		sD3D->SetTexture(0, m_pPreview);
		sD3D->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, backg, sizeof(Vertex3FRHWT));
	}
	m_pModelTree->Draw();
	ui32 numItems = m_pModelTree->GetNumItems() - 1;
	if(numItems != m_numLastItems)
	{
		m_numLastItems = numItems;
		ui32 value = m_pTreeScroll->GetValue();
		m_pTreeScroll->SetRange(0, numItems);
		m_pTreeScroll->SetValue(value);
	}
	m_pTreeScroll->Draw();
	sD3D->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
}

void BrowsingUI::ReloadVertices()
{
	float& x = m_position.x;
	float& y = m_position.y;

	m_topR[0].x = x + 255;
	m_topR[0].y = y;
	m_topR[0].u = 1 / 128.0f;
	m_topR[0].v = 1 / 256.0f;
	m_topR[1].x = x + 255 + 97;
	m_topR[1].y = y;
	m_topR[1].u = 96.0f / 128.0f;
	m_topR[1].v = 1 / 256.0f;
	m_topR[2].x = x + 255 + 97;
	m_topR[2].y = y + 255.0f;
	m_topR[2].u = 96.0f / 128.0f;
	m_topR[2].v = 1.0f;
	m_topR[3].x = x + 255;
	m_topR[3].y = y + 255.0f;
	m_topR[3].u = 1 / 128.0f;
	m_topR[3].v = 1.0f;

	m_topL[0].x = x;
	m_topL[0].y = y;
	m_topL[0].u = 1 / 256.0f;
	m_topL[0].v = 1 / 256.0f;
	m_topL[1].x = x + 257.0f;
	m_topL[1].y = y;
	m_topL[1].u = 255.0f / 256.0f;
	m_topL[1].v = 1 / 256.0f;
	m_topL[2].x = x + 257.0f;
	m_topL[2].y = y + 255.0f;
	m_topL[2].u = 255.0f / 256.0f;
	m_topL[2].v = 1.0f;
	m_topL[3].x = x;
	m_topL[3].y = y + 255.0f;
	m_topL[3].u = 1 / 256.0f;
	m_topL[3].v = 1.0f;

	m_botL[0].x = x;
	m_botL[0].y = y + 255.0f - 1.0f;
	m_botL[0].u = 1 / 256.0f;
	m_botL[0].v = 1 / 256.0f;
	m_botL[1].x = x + 257.0f;
	m_botL[1].y = y + 255.0f - 1.0f;
	m_botL[1].u = 255.0f / 256.0f;
	m_botL[1].v = 1 / 256.0f;
	m_botL[2].x = x + 257.0f;
	m_botL[2].y = y + 439;
	m_botL[2].u = 255.0f / 256.0f;
	m_botL[2].v = 184.0f / 256.0f;
	m_botL[3].x = x;
	m_botL[3].y = y + 439;
	m_botL[3].u = 1 / 256.0f;
	m_botL[3].v = 184.0f / 256.0f;

	m_botR[0].x = x + 255;
	m_botR[0].y = y + 255.0f - 1.0f;
	m_botR[0].u = 1 / 128.0f;
	m_botR[0].v = 1 / 256.0f;
	m_botR[1].x = x + 255 + 97;
	m_botR[1].y = y + 255.0f - 1.0f;
	m_botR[1].u = 96.0f / 128.0f;
	m_botR[1].v = 1 / 256.0f;
	m_botR[2].x = x + 255 + 97;
	m_botR[2].y = y + 439;
	m_botR[2].u = 96.0f / 128.0f;
	m_botR[2].v = 184.0f / 256.0f;
	m_botR[3].x = x + 255;
	m_botR[3].y = y + 439;
	m_botR[3].u = 1 / 128.0f;
	m_botR[3].v = 184.0f / 256.0f;
}

bool BrowsingUI::OnMouseClick(Vertex2F pos, bool up)
{
	m_pModelTree->MouseActivity(false, pos, up);
	m_pTreeScroll->MouseActivity(false, pos, up);
	if(pos.x >= m_position.x + 68.0f && pos.y >= m_position.y + 11.0f && pos.x <= m_position.x + 325.0f && pos.y <= m_position.y + 32)
	{
		m_relClick.x = pos.x - m_position.x;
		m_relClick.y = pos.y - m_position.y;
		m_titleClicked = !up;
		return true;
	}
	m_titleClicked = false;
	return false;
}

void BrowsingUI::OnMouseMove(Vertex2F pos)
{
	m_pTreeScroll->OnMouseMove(pos.x, pos.y, false, false);
	if(!m_titleClicked)
		return;

	Vertex2F posOld = m_position;

	m_position.y = pos.y - m_relClick.y;
	m_position.x = pos.x - m_relClick.x;
	m_pModelTree->ModPosition(m_position.x - posOld.x, m_position.y - posOld.y);
	m_pTreeScroll->ModPosition(m_position.x - posOld.x, m_position.y - posOld.y);

	ReloadVertices();
}

void BrowsingUI::Render3D()
{
	if(!m_pModel)
		return;

	if(!m_pPreview)
		D3DXCreateTexture(sD3D, 150, 150, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_pPreview);

	WINDOWINFO inf;
	GetWindowInfo(sWindow, &inf);
	POINT ptM;
	GetCursorPos(&ptM);
	ptM.x -= inf.rcClient.left;
	ptM.y -= inf.rcClient.top;

	if(ptM.x >= m_position.x + 40 && ptM.x <= m_position.x + 190 && ptM.y >= m_position.y + 80 && ptM.y <= m_position.y + 230)
	{
		BYTE pBytes[256];
		GetKeyboardState(pBytes);
		if(pBytes[0x51] & 0x80)
			m_rotationY += 0.8f;
		if(pBytes[0x45] & 0x80)
			m_rotationY -= 0.8f;
		if(pBytes[0x57] & 0x80)
			m_distX -= 0.5f;
		if(pBytes[0x53] & 0x80)
			m_distX += 0.5f;
	}

	IDirect3DSurface9* pSurface, *pOldSurface;
	m_pPreview->GetSurfaceLevel(0, &pSurface);

	sD3D->GetRenderTarget(0, &pOldSurface);
	sD3D->SetRenderTarget(0, pSurface);

	D3DXMATRIX matViewOld, matViewNew, matProjOld, matProjNew;
	D3DXVECTOR3 eye(m_distX, 0, 0), at(0, 0, 0), up(0, 1, 0);
	D3DXMatrixLookAtLH(&matViewNew, &eye, &at, &up);
	D3DXMatrixPerspectiveFovLH(&matProjNew, D3DXToRadian(45.0f), 150.0f / 150.0f, 0.1f, 1000.0f);

	sD3D->GetTransform(D3DTS_VIEW, &matViewOld);
	sD3D->GetTransform(D3DTS_PROJECTION, &matProjOld);
	sD3D->SetTransform(D3DTS_VIEW, &matViewNew);
	sD3D->SetTransform(D3DTS_PROJECTION, &matProjNew);

	sD3D->BeginScene();

	sD3D->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
	sD3D->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	sD3D->SetRenderState(D3DRS_LIGHTING, FALSE);
	DWORD dwZenabled = 0.0f;
	sD3D->GetRenderState(D3DRS_ZENABLE, &dwZenabled);
	sD3D->SetRenderState(D3DRS_ZENABLE, TRUE);
	sD3D->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);

	m_pModel->SetRotation(0.0f, m_rotationY, 0.0f);
	m_pModel->Draw(Vertex3F(10, 0, 0), Vertex3F(0, 0, 0));

	sD3D->EndScene();

	sD3D->SetRenderTarget(0, pOldSurface);
	sD3D->SetTransform(D3DTS_VIEW, &matViewOld);
	sD3D->SetTransform(D3DTS_PROJECTION, &matProjOld);
	sD3D->SetRenderState(D3DRS_ZENABLE, dwZenabled);
}

void BrowsingUI::ParsePath(TreeViewItem* pItem, std::string szBase)
{
	std::string path = szBase + "Models.txt";
	CMpqFile mList(path);

	if(mList.IsOpened())
	{
		char* pData = new char[mList.GetSize()];
		mList.Read(0, mList.GetSize(), pData);
		std::string s = pData;
		delete [] pData;

		std::string::size_type pos;

		while((pos = s.find('\n')) != std::string::npos)
		{
			std::string tmp = s.substr(0, pos - 1);
			char curPath[255];
			sprintf(curPath, "%s%s\\", szBase.c_str(), tmp.c_str());
			if(tmp.find('\n') != 0)
			{
				TreeViewItem* pSub = pItem->AddSubItem(tmp);
				ParsePath(pSub, curPath);
			}
			s = s.substr(pos + 1, s.length());
		}
	}

	path = szBase + "Files.txt";
	CMpqFile fl(path);
	if(!fl.IsOpened())
		return;

	char* pData = new char[fl.GetSize()];
	fl.Read(0, fl.GetSize(), pData);
	std::string s = pData;
	delete [] pData;
	std::string::size_type pos;
	while((pos = s.find('\n')) != std::string::npos)
	{
		std::string tmp = s.substr(0, pos - 1);
		if(tmp.find('\n') != 0)
			pItem->AddSubItem(tmp.substr(0, tmp.length() - 1));
		s = s.substr(pos + 1, s.length());
	}
}

void BrowsingUI::LoadModels()
{
	CMpqFile mList("Models\\Models.txt");
	if(!mList.IsOpened())
		return;

	char* pData = new char[mList.GetSize()];
	mList.Read(0, mList.GetSize(), pData);
	std::string s = pData;
	delete [] pData;

	char curPath[255];
	sprintf(curPath, "Models\\");

	std::string::size_type pos;

	while((pos = s.find('\n')) != std::string::npos)
	{
		std::string tmp = s.substr(0, pos - 1);
		sprintf(curPath, "Models\\%s\\", tmp.c_str());
		TreeViewItem* pItem = new TreeViewItem(tmp);
		m_pModelTree->AddItem(pItem);
		ParsePath(pItem, curPath);
		s = s.substr(pos + 1, s.length());
	}
}